/*
 * Copyright 2010 Aekold Helbrass
 * 
 * This file is part of RosterComposer.
 * 
 * RosterComposer is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 * 
 * RosterComposer is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 * 
 * You should have received a copy of the GNU General Public License
 * along with RosterComposer.  If not, see <http://www.gnu.org/licenses/>.
 */
package org.heresylabs.rostercomposer;

import java.awt.Component;
import java.awt.GridLayout;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.util.ArrayList;
import java.util.List;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTree;
import javax.swing.ToolTipManager;
import javax.swing.event.TreeModelListener;
import javax.swing.tree.DefaultTreeCellRenderer;
import javax.swing.tree.TreeModel;
import javax.swing.tree.TreePath;
import javax.swing.tree.TreeSelectionModel;
import org.heresylabs.rostercomposer.units.Category;
import org.heresylabs.rostercomposer.units.Unit;

/**
 *
 * @author Aekold Helbrass <Helbrass@gmail.com>
 */
public class UnitsListPanel extends JPanel {

    private final Composer composer;
    private final List<? extends Category> categories;
    private final JTree unitsTree;

    public UnitsListPanel(final Composer composer) {
        super(new GridLayout(1, 1));
        this.composer = composer;
        this.categories = composer.getArmy().getCategories();

        unitsTree = new JTree(new UnitsTreeModel());
        unitsTree.setEditable(false);
        unitsTree.setRootVisible(false);
        unitsTree.setScrollsOnExpand(true);
        unitsTree.setToggleClickCount(1);
        unitsTree.setCellRenderer(new CellRenderer());
        unitsTree.getSelectionModel().setSelectionMode(TreeSelectionModel.SINGLE_TREE_SELECTION);
        unitsTree.addMouseListener(new MouseAdapter() {

            @Override
            public void mouseClicked(MouseEvent e) {
                if (e.getClickCount() != 2) {
                    return;
                }
                addSelectedUnit();
            }

        });
        unitsTree.addKeyListener(new KeyAdapter() {

            @Override
            public void keyPressed(KeyEvent e) {
                if (e.getKeyCode() != KeyEvent.VK_ENTER) {
                    return;
                }
                addSelectedUnit();
            }

        });
        ToolTipManager.sharedInstance().registerComponent(unitsTree);

        for (int i = unitsTree.getRowCount() - 1; i >= 0; i--) {
            unitsTree.expandRow(i);
        }

        JScrollPane scroll = new JScrollPane(unitsTree);
        add(scroll);
    }

    private void addSelectedUnit() {
        // TODO current implementation is based on depth of 3: Root, Category, Unit. It's not very flexible
        TreePath treePath = unitsTree.getSelectionPath();
        if (treePath == null || treePath.getPathCount() != 3) {
            return;
        }
        Category category = (Category) treePath.getPathComponent(1);
        Unit unit = (Unit) treePath.getPathComponent(2);
        composer.addUnit(unit, category);
    }

    private class UnitsTreeModel implements TreeModel {

        private static final String ROOT_NODE = "Root";
        private final List<TreeModelListener> listeners = new ArrayList<TreeModelListener>();

        @Override
        public Object getRoot() {
            return ROOT_NODE;
        }

        @Override
        public Object getChild(Object parent, int index) {
            if (parent == ROOT_NODE) {
                return categories.get(index);
            }
            if (parent instanceof Category) {
                Category cat = (Category) parent;
                return cat.getUnits().get(index);
            }
            return null;
        }

        @Override
        public int getChildCount(Object parent) {
            if (parent == ROOT_NODE) {
                return categories.size();
            }
            if (parent instanceof Category) {
                List<? extends Unit> units = ((Category) parent).getUnits();
                if (units == null || units.isEmpty()) {
                    return 0;
                }
                return units.size();
            }
            return 0;
        }

        @Override
        public boolean isLeaf(Object node) {
            return !(node == ROOT_NODE || node instanceof Category);
        }

        @Override
        public void valueForPathChanged(TreePath path, Object newValue) {
        }

        @Override
        public int getIndexOfChild(Object parent, Object child) {
            throw new UnsupportedOperationException("Not supported yet.");
        }

        @Override
        public void addTreeModelListener(TreeModelListener l) {
            listeners.add(l);
        }

        @Override
        public void removeTreeModelListener(TreeModelListener l) {
            listeners.remove(l);
        }

    }

    private class CellRenderer extends DefaultTreeCellRenderer {

        @Override
        public Component getTreeCellRendererComponent(JTree tree, Object value, boolean sel, boolean expanded, boolean leaf, int row, boolean hasFocus) {
            JLabel label = (JLabel) super.getTreeCellRendererComponent(tree, value, sel, expanded, leaf, row, hasFocus);
            if (value instanceof Unit) {
                Unit unit = (Unit) value;
                label.setText(unit.getName());
                label.setToolTipText(
                        "<html><b>"
                        + unit.getName()
                        + "</b><br/><small>cost:</small>&nbsp;"
                        + unit.getCost()
                        + "<br/><small>number/squad</small>:&nbsp;"
                        + (unit.getMinNumber() == unit.getMaxNumber() ? unit.getMinNumber() : unit.getMinNumber() + "-" + unit.getMaxNumber()));
            }
            return label;
        }

    }

}
